package cn.wetcland.urban.framework.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import cn.wetcland.urban.common.MyAssert;
import cn.wetcland.urban.common.controller.CommonController;
import cn.wetcland.urban.common.pojo.PathPlanningPOJO;
import cn.wetcland.urban.common.utils.CopyObjectUtil;
import cn.wetcland.urban.framework.dto.CustomerCreateOrderDTO;
import cn.wetcland.urban.framework.dto.CustomerDeleteOrderListDTO;
import cn.wetcland.urban.framework.dto.CustomerEvaluationDTO;
import cn.wetcland.urban.framework.mapper.*;
import cn.wetcland.urban.framework.service.UtOrderService;
import cn.wetcland.urban.framework.utils.StpDriverUtil;
import cn.wetcland.urban.framework.vo.*;
import cn.wetcland.urban.generator.domain.*;
import cn.wetcland.urban.generator.dto.BaseConditionSearchDTO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
* @author Wetcland
* @description 针对表【ut_order】的数据库操作Service实现
* @createDate 2024-01-21 09:51:59
*/
@Service
public class UtOrderServiceImpl extends ServiceImpl<UtOrderMapper, UtOrder> implements UtOrderService {

    @Resource
    public UtOrderMapper orderMapper;

    @Resource
    public UtCustomerAddressMapper addressMapper;

    @Resource
    public UtDriverMapper driverMapper;

    @Resource
    public UtCarMapper carMapper;

    @Resource
    public UtRouteMapper routeMapper;

    @Resource
    public UtPathStepMapper pathStepMapper;

    @Resource
    public UtEvaluationMapper evaluationMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleCustomerCreateOrder(CustomerCreateOrderDTO customerCreateOrderDTO) {
        MyAssert.isTrue(!Objects.equals(customerCreateOrderDTO.getOriginAddressId(), customerCreateOrderDTO.getDestinationAddressId()), "起始地与目的地一致");
        UtCustomerAddress utCustomerAddress = addressMapper.selectById(customerCreateOrderDTO.getOriginAddressId());
        MyAssert.notNull(utCustomerAddress, "起始地址不存在");
        UtCustomerAddress utCustomerAddress1 = addressMapper.selectById(customerCreateOrderDTO.getDestinationAddressId());
        MyAssert.notNull(utCustomerAddress1, "目的地址不存在");
        MyAssert.isTrue(Objects.equals(utCustomerAddress.getAddressCityId(), utCustomerAddress1.getAddressCityId()), "起始地与目的地不在同一市区");
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("key", CommonController.amapKey);
        paramMap.put("origin", utCustomerAddress.getLongitude().toPlainString()+","+utCustomerAddress.getLatitude().toPlainString());
        paramMap.put("destination", utCustomerAddress1.getLongitude().toPlainString()+","+utCustomerAddress1.getLatitude().toPlainString());
        paramMap.put("extensions", "all");
        paramMap.put("output", "json");
        String s = HttpUtil.get("https://restapi.amap.com/v3/direction/driving", paramMap);
        PathPlanningPOJO bean = JSONUtil.parseObj(s).toBean(PathPlanningPOJO.class);
        MyAssert.isTrue(Objects.equals(bean.getStatus(), "1"), "高德地图API配额不足");

        UtOrder utOrder = new UtOrder();
        utOrder.setOriginAddressId(customerCreateOrderDTO.getOriginAddressId());
        utOrder.setDestinationAddressId(customerCreateOrderDTO.getDestinationAddressId());
        utOrder.setCustomerId(StpUtil.getLoginIdAsLong());
        utOrder.setOrderSn(UUID.fastUUID().toString(true));
        utOrder.setOriginLocationLongitude(utCustomerAddress.getLongitude());
        utOrder.setOriginLocationLatitude(utCustomerAddress.getLatitude());
        utOrder.setOriginLocationName(utCustomerAddress.getAddressDetails());

        utOrder.setDestinationLocationLongitude(utCustomerAddress1.getLongitude());
        utOrder.setDestinationLocationLatitude(utCustomerAddress1.getLatitude());
        utOrder.setDestinationLocationName(utCustomerAddress1.getAddressDetails());

        // 高德地图计算的打车费用
        utOrder.setPrice(new BigDecimal(bean.getRoute().getTaxiCost()));

        utOrder.setFollowerNum(customerCreateOrderDTO.getFollowerNum());
        // 等待接单
        utOrder.setOrderStatus(0);
        orderMapper.insert(utOrder);

        PathPlanningPOJO.RouteDTO route = bean.getRoute();
        if (route.getPaths().isEmpty()) {
            // 若规划路径为空，不插入路径数据
            return;
        }
        PathPlanningPOJO.RouteDTO.PathsDTO path = route.getPaths().get(0);
        UtRoute utRoute = new UtRoute();
        utRoute.setCost(new BigDecimal(route.getTaxiCost()));
        utRoute.setOrderId(utOrder.getOrderId());
        utRoute.setDistance(Double.valueOf(path.getDistance()));
        utRoute.setDuration(path.getDuration());
        utRoute.setOriginAddressId(utOrder.getOriginAddressId());
        utRoute.setOriginName(utOrder.getOriginLocationName());
        utRoute.setDestinationAddressId(utOrder.getDestinationAddressId());
        utRoute.setDestinationName(utOrder.getDestinationLocationName());
        routeMapper.insert(utRoute);
        // 插入路径步骤
        for (PathPlanningPOJO.RouteDTO.PathsDTO.StepsDTO step : path.getSteps()) {
            UtPathStep utPathStep = new UtPathStep();
            CopyObjectUtil.copyPropertiesIgnoreNull(step, utPathStep);
            utPathStep.setRouteId(utRoute.getRouteId());
            utPathStep.setDistance(Double.valueOf(step.getDistance()));
            utPathStep.setDuration(Double.valueOf(step.getDuration()));
            utPathStep.setWalkType(step.getRoad());
            pathStepMapper.insert(utPathStep);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleCustomerDeleteOrder(CustomerDeleteOrderListDTO deleteOrderListDTO) {
        orderMapper.deleteBatchIds(deleteOrderListDTO.getOrderIds());
    }

    @Override
    public Page<CustomerOrderListItemVO> customerOrderList(Integer status, BaseConditionSearchDTO searchDTO) {
        Page<CustomerOrderListItemVO> customerOrderListItemVOPage = new Page<>(searchDTO.getCurPage(), searchDTO.getPageSize());
        long loginIdAsLong = StpUtil.getLoginIdAsLong();
        return orderMapper.customerOrderListByCustomerId(customerOrderListItemVOPage, status, loginIdAsLong, searchDTO);
    }

    @Override
    public CustomerOrderDetailsVO customerOrderDetails(Long id) {
        CustomerOrderDetailsVO customerOrderDetailsVO = orderMapper.customerOrderDetails(id);
        MyAssert.notBlank(customerOrderDetailsVO.getCarNo(), "车型未审核");
        return customerOrderDetailsVO;
    }

    @Override
    public Page<DriverGainOrderListItemVO> handleDriverGainOrderList(BaseConditionSearchDTO searchDTO) {
        Page<DriverGainOrderListItemVO> driverGainOrderListItemVOPage = new Page<>(searchDTO.getCurPage(), searchDTO.getPageSize());
        long loginIdAsLong = StpDriverUtil.getLoginIdAsLong();
        return orderMapper.driverGainOrderList(driverGainOrderListItemVOPage, searchDTO, loginIdAsLong);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleDriverGainOrder(Long orderId) {
        long loginIdAsLong = StpDriverUtil.getLoginIdAsLong();
        UtDriver driver = driverMapper.selectById(loginIdAsLong);
        UtOrder utOrder = orderMapper.selectById(orderId);
        MyAssert.notNull(utOrder, "该订单不存在");
        UtCar car = carMapper.selectOne(new QueryWrapper<UtCar>().eq("driver_id", loginIdAsLong));
        MyAssert.notNull(car, "未审核车辆");
        UtCustomerAddress utCustomerAddress = addressMapper.selectById(utOrder.getOriginAddressId());
        MyAssert.notNull(utCustomerAddress, "订单地址不存在");
        MyAssert.isTrue(Objects.equals(driver.getCityId(), utCustomerAddress.getAddressCityId()), "不在同一城市");
        utOrder.setDriverId(loginIdAsLong);
        utOrder.setOrderStatus(1);
        orderMapper.updateById(utOrder);
    }

    @Override
    public Page<DriverOrderListItemVO> driverOrderList(Integer status, BaseConditionSearchDTO searchDTO) {
        Page<CustomerOrderListItemVO> customerOrderListItemVOPage = new Page<>(searchDTO.getCurPage(), searchDTO.getPageSize());
        long loginIdAsLong = StpDriverUtil.getLoginIdAsLong();
        return orderMapper.driverOrderListByDriverId(customerOrderListItemVOPage, status, loginIdAsLong, searchDTO);
    }

    @Override
    public DriverOrderMapVO driverOrderMap(Long id) {
        UtOrder utOrder = orderMapper.selectById(id);
        MyAssert.notNull(utOrder, "该订单不存在");
        UtRoute route = routeMapper.selectOne(new QueryWrapper<UtRoute>().eq("order_id", id));
        MyAssert.notNull(route, "该路径不存在");
        List<UtPathStep> steps = pathStepMapper.selectList(new QueryWrapper<UtPathStep>()
                .eq("route_id", route.getRouteId())
        );
        UtCustomerAddress utCustomerAddress = addressMapper.selectById(utOrder.getOriginAddressId());
        UtCustomerAddress utCustomerAddress1 = addressMapper.selectById(utOrder.getDestinationAddressId());
        DriverOrderMapVO orderMapVO = new DriverOrderMapVO();
        orderMapVO.setOriginLongitude(utCustomerAddress.getLongitude());
        orderMapVO.setOriginLatitude(utCustomerAddress.getLatitude());
        orderMapVO.setDestinationLongitude(utCustomerAddress1.getLongitude());
        orderMapVO.setDestinationLatitude(utCustomerAddress1.getLatitude());
        CopyObjectUtil.copyPropertiesIgnoreNull(route, orderMapVO);
        // 115.870599,28.737089;115.870581,28.737122;
        List<DriverOrderMapVO.Step> stepList = new ArrayList<>();
        for (UtPathStep step : steps) {
            DriverOrderMapVO.Step step1 = new DriverOrderMapVO.Step();
            CopyObjectUtil.copyPropertiesIgnoreNull(step, step1);
            String polyline = step.getPolyline();
            String[] split = polyline.split(";");
            List<DriverOrderMapVO.PolylineItem> polylineItems = new ArrayList<>();
            for (String s : split) {
                String[] split1 = s.split(",");
                DriverOrderMapVO.PolylineItem polylineItem = new DriverOrderMapVO.PolylineItem();
                polylineItem.setLongitude(new BigDecimal(split1[0]));
                polylineItem.setLatitude(new BigDecimal(split1[1]));
                polylineItems.add(polylineItem);
            }
            step1.setPolylineItems(polylineItems);
            stepList.add(step1);
        }
        orderMapVO.setSteps(stepList);
        return orderMapVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void driverOrderGainGoods(Long orderId) {
        UtOrder utOrder = orderMapper.selectById(orderId);
        MyAssert.notNull(utOrder, "订单不存在");
        MyAssert.isTrue(utOrder.getOrderStatus() == 1, "订单还未被司机接单");
        utOrder.setOrderStatus(2);
        orderMapper.updateById(utOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void driverOrderDropGoods(Long orderId) {
        UtOrder utOrder = orderMapper.selectById(orderId);
        MyAssert.notNull(utOrder, "订单不存在");
        MyAssert.isTrue(utOrder.getOrderStatus() == 2, "订单还未装货");
        utOrder.setOrderStatus(3);
        orderMapper.updateById(utOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void customerOrderConfirmEvaluation(CustomerEvaluationDTO evaluationDTO) {
        UtOrder utOrder = orderMapper.selectById(evaluationDTO.getOrderId());
        MyAssert.notNull(utOrder, "订单不存在");
        MyAssert.isTrue(utOrder.getOrderStatus() == 3, "订单还未确认");
        UtEvaluation utEvaluation1 = evaluationMapper.selectOne(new QueryWrapper<UtEvaluation>().eq("order_id", evaluationDTO.getOrderId()));
        MyAssert.isNull(utEvaluation1, "该订单已被评价过");
        UtEvaluation utEvaluation = new UtEvaluation();
        CopyObjectUtil.copyPropertiesIgnoreNull(evaluationDTO, utEvaluation);
        utOrder.setOrderStatus(4);
        orderMapper.updateById(utOrder);
        utEvaluation.setEvaluationCustomerId(StpUtil.getLoginIdAsLong());
        evaluationMapper.insert(utEvaluation);
    }

    @Override
    public void customerOrderCancel(Long orderId) {
        long loginIdAsLong = StpUtil.getLoginIdAsLong();
        UtOrder utOrder = orderMapper.selectById(orderId);
        MyAssert.isTrue(utOrder.getCustomerId() == loginIdAsLong, "该订单不属于该用户");
        MyAssert.isTrue(utOrder.getOrderStatus() == 0 || utOrder.getOrderStatus() == 1, "只能在还未装车前取消订单");
        utOrder.setOrderStatus(5);
        orderMapper.updateById(utOrder);
    }

}




